import VisualBase from './VisualBase';
import {
  ctxDrawCircle, 
  ctxDrawRectangle, 
  ctxDrawLine,
  ctxDrawString,
} from './ctxDraw';

const DEFAULT_FONT       = 'Verdana';
const DEFAULT_FONTSIZE   = 16;

class Canvas2DBase extends VisualBase{

  constructor(width=100, height=100, bgColor='#FFFFFF'){
    super('Canvas2DBase');

    // var domElement = document.createElement('div');
    // // domElement.style.display   = 'flex';
    // // domElement.style.backgroundColor = '#000000';
    // domElement.style.border = "1px solid #000000";
    // domElement.style.margin = '2px';
    const domElement  = this.domElement;

    var canvas    = document.createElement('canvas'); 
    canvas.width  = width;
    canvas.height = height;
    canvas.style.backgroundColor = bgColor;
    canvas.style.margin  = '0 auto';
    canvas.style.display = 'block';
    this.canvas   = canvas;

    domElement.appendChild(canvas); 

    // 背景色
    this.addAttribute('bgColor'   , bgColor , 'color'   , '通用');    

    this.init();

    // 鼠标事件
    this.startPositon = [0, 0];
    this.endPostion   = [0, 0];


    // 初始化鼠标输入事件
    this.initInput();
  } 
  // 初始化图
  init(){
    // 字体
    this.addAttribute('font'        , DEFAULT_FONT        , 'string'  , '外观');
    this.addAttribute('fontSize'    , DEFAULT_FONTSIZE    , 'number'  , '外观');
    // 大小
    this.addAttribute('width'       , this.canvas.width   , 'number'  , '尺寸');
    this.addAttribute('height'      , this.canvas.height  , 'number'  , '尺寸');
    this.addAttribute('fitToWindow' , false               , 'boolean' , '尺寸');
    // 位置
    this.addAttribute('paddingX', 20, 'number', '尺寸');
    this.addAttribute('paddingY', 20, 'number', '尺寸');
    
    // 边框
    this.addAttribute('showBorder'  , true      , 'boolean'   , '边框');
    this.addAttribute('border'      , 2         , 'number'    , '边框');
    this.addAttribute('borderColor' , '#000000' , 'color'     , '边框');
    this.addAttribute('borderStyle' , 'solid'   , 'lineStyle' , '边框');

    // 网格
    this.addAttribute('showGrid'  , true      , 'boolean'   , '网格');
    this.addAttribute('grid'      , 1         , 'number'    , '网格');
    this.addAttribute('gridX'     , 10        , 'number'    , '网格');
    this.addAttribute('gridY'     , 10        , 'number'    , '网格');
    this.addAttribute('gridColor' , '#666666' , 'color'     , '网格');
    this.addAttribute('gridStyle' , 'dashed'  , 'lineStyle' , '网格');

    // 鼠标事件
    this.addAttribute('eventDrawRect'  , false, 'boolean', '事件');
    this.addAttribute('eventDrawLine'  , false, 'boolean', '事件');
    this.addAttribute('eventDrawPoint' , false, 'boolean', '事件');
    this.addAttribute('eventDrawCursor', false, 'boolean', '事件');
  }


  // 获取字符串宽度
  getTextWidth(str){
    const canvas  = this.canvas;

    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      ctx.font = `${this.fontSize}px ${this.font}`;
      const txtWidth = ctx.measureText(str).width;
      return txtWidth;
    }
    return -1;
  }

  // 绘制矩形
  _drawRectangle(x, y, w, h, fill=false, color='#000000', lineWidth=2, lineStyle=[]){
    const canvas  = this.canvas;

    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      ctxDrawRectangle(ctx, x, y, w, h, fill, color, lineWidth, lineStyle);
    }
  }

  // 窗口位置绘制矩形
  _drawRectangleByWindowPosition(wx, wy, w, h, fill=false, color='#000000', lineWidth=2, lineStyle=[]){
    const pos = this.windowPositionToLocalPosition(wx, wy);

    if(pos !== undefined){
      this._drawRectangle(pos[0], pos[1], w, h, fill, color, lineWidth, lineStyle);
    }
  }

  // 绘制圆
  _drawCircle(cx, cy, r=5, fill=false, start=0, end=360, color='#000000', lineWidth=2, lineStyle=[]){
    const canvas  = this.canvas;

    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      ctxDrawCircle(ctx, cx, cy, r, fill, start, end, color, lineWidth, lineStyle);
    }
  }

  // 窗口位置绘制圆
  _drawCircleByWindowPosition(wx, wy, r=5, fill=false, start=0, end=360, color='#000000', lineWidth=2, lineStyle=[]){
    const pos = this.windowPositionToLocalPosition(wx, wy);

    if(pos !== undefined){
      this._drawCircle(pos[0], pos[1], r, fill, start, end, color, lineWidth, lineStyle);
    }
  }
  
  // 绘制线段
  _drawLine(x1, y1, x2, y2, lineWidth=2, lineStyle=[], color='#000000'){
    const canvas  = this.canvas;

    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      ctxDrawLine(ctx, x1, y1, x2, y2, lineWidth, lineStyle, color);
    }
  }

  _drawLineByWindowPosition(wx1, wy1, wx2, wy2, lineWidth=2, lineStyle=[], color='#000000'){
    const pos1 = this.windowPositionToLocalPosition(wx1, wy1);
    const pos2 = this.windowPositionToLocalPosition(wx2, wy2);
    if(pos1 !== undefined && pos2 !== undefined){
      this._drawLine(pos1[0], pos1[1], pos2[0], pos2[1], lineWidth, lineStyle, color);
    }
  }
  
  // 绘制字符串
  _drawString(str, x, y, color='#000000', font=this.font, size=this.fontSize, fill=true, lineWidth=1, lineStyle=[], fixPosition=true){
    const canvas  = this.canvas;

    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      const txtWidth = ctx.measureText(str).width;

      // 修复位置以显示在画图范围内
      if(fixPosition){
        if(x > this.width / 2){
          x -= txtWidth;
        }
        if(y < this.height / 2){
          y += parseFloat(size);
        }
      }

      ctxDrawString(ctx, str, x, y, color, font, size, fill, lineWidth, lineStyle);
    }
  }

  _drawStringByWindowPosition(str, wx, wy, color='#000000', font=this.font, size=this.fontSize, fill=true, lineWidth=2, lineStyle=[]){
    const pos = this.windowPositionToLocalPosition(wx, wy);
    if(pos !== undefined){
      this._drawString(str, pos[0], pos[1], color, font, parseFloat(size), fill, lineWidth, lineStyle);
    }
  }

  // 绘制游标
  _drawCursor(x, y){
    this._drawLine(x, this.paddingY, x, this.height - this.paddingY);
    this._drawLine(this.paddingX, y, this.width - this.paddingX, y);
    this._drawString(`(${x-this.paddingX},${y-this.paddingY})`, x, y);
  }
  // 绘制点信息
  _drawPoint(x, y){
    this._drawCircle(x, y, 3, true);
    this._drawString(`(${x-this.paddingX},${y-this.paddingY})`, x, y);
  }
  // 绘制线段信息
  _drawLineInfo(x1, y1, x2, y2){
    const w = x2 - x1;
    const h = y2 - y1;
    const len = Math.sqrt(w*w + h*h).toFixed(2);
    this._drawStringByWindowPosition( `Line:${len}`, x2, y2);
  }
  // 绘制矩形信息
  _drawRectInfo(x1, y1, x2, y2){
    const w = x2 - x1;
    const h = y2 - y1;
    this._drawStringByWindowPosition( `Rect:[${w}x${h}]`, x1, y1);
  }

  // 绘制边框
  drawBorder(){
    if(!this.showBorder) return;
  
    const x = parseInt(this.paddingX);
    const y = parseInt(this.paddingY);
    const w = this.width  - x * 2;
    const h = this.height - y * 2; 

    const fill      = false;
    const color     = this.borderColor;
    const lineWidth = this.border;
    const lineStyle = this.lineStyle[this.borderStyle];

    this._drawRectangle(x, y, w, h, fill, color, lineWidth, lineStyle);
  }

  // 绘制网格
  drawGrid(){
    if(!this.showGrid) return;

    const x = parseInt(this.paddingX);
    const y = parseInt(this.paddingY);
    const w = this.width  - x * 2;
    const h = this.height - y * 2; 

    const color     = this.gridColor;
    const lineWidth = this.grid;
    const lineStyle = this.lineStyle[this.gridStyle];

    const nx = parseInt(this.gridX);
    const ny = parseInt(this.gridY);

    const stepX = w / nx;
    const stepY = h / ny;

    // X方向
    for(var iy = 1; iy < ny; iy++){
      this._drawLine(x, iy * stepY + y, w + x, iy * stepY + y, lineWidth, lineStyle, color );
    }

    // Y方向
    for(var ix = 1; ix < nx; ix++){
      this._drawLine(ix * stepX + x, h + y, ix * stepX + x, y, lineWidth, lineStyle, color );
    }
  }

  // 获取窗口位置对应的画布位置
  windowPositionToLocalPosition(wx, wy){
    const canvas   = this.canvas;
    const paddingX = parseInt(this.paddingX);
    const paddingY = parseInt(this.paddingY);
    const w        = this.width;
    const h        = this.height;

    // 点在画布中的位置=窗口位置+页面滚动值-画布的偏移
    let x = parseInt(wx) + parseInt(window.scrollX) - parseInt(canvas.offsetLeft);
    let y = parseInt(wy) + parseInt(window.scrollY) - parseInt(canvas.offsetTop) ;
    
    if(x >= paddingX && x <= w - paddingX
      && y >= paddingY && y <= h - paddingY){
      return [x, y];
    }

    return undefined;
  }

  // 鼠标事件
  onMouseDown(event){
    const x = event.x;
    const y = event.y;
    const pos = this.windowPositionToLocalPosition(x, y);
    if(pos === undefined){
      this.mouseIsDown = false;
      return;
    }
    this.startPositon = [x, y];
    this.mouseIsDown  = true;

    if(this.eventDrawPoint){
      this._drawPoint(pos[0], pos[1]);
    }
  }

  onMouseMove(event){
    const x = event.x;
    const y = event.y;
    const pos = this.windowPositionToLocalPosition(x, y);

    if(pos === undefined) return;

    this.update();

    if(this.mouseIsDown){
      const w = x - this.startPositon[0];
      const h = y - this.startPositon[1];
      this.endPostion = [x, y];

      if(this.eventDrawLine){
        this._drawLineByWindowPosition(this.startPositon[0], this.startPositon[1], this.endPostion[0], this.endPostion[1]);
        this._drawLineInfo( this.startPositon[0], this.startPositon[1], this.endPostion[0], this.endPostion[1] );
      }

      if(this.eventDrawRect){
        this._drawRectangleByWindowPosition(this.startPositon[0], this.startPositon[1], w, h);
        this._drawRectInfo(this.startPositon[0], this.startPositon[1], this.endPostion[0], this.endPostion[1]);
      }
    }

    if(this.eventDrawCursor){
      this._drawCursor(pos[0], pos[1]);
    }
  }

  onMouseUp(event){
    const x = event.x;
    const y = event.y;

    if(this.windowPositionToLocalPosition(x, y) === undefined){
      if(this.mouseIsDown){
        this.clear();
        this.update();
        this.mouseIsDown = false;
      }
      return;
    }

    this.clear();
    this.update();
    this.mouseIsDown = false;
  }
  // 重置大小
  resize(){
    if(this.fitToWindow){
      const ratio = this.height / this.width;
      this.width = this.domElement.clientWidth;
      this.height = this.width * ratio;
    }
    this.canvas.width  = this.width;
    this.canvas.height = this.height;
  }

  // 绘制成员列表
  renderItems(){
    for(var i=0, il= this.items.length; i < il; i++){
      this.items[i].draw(this);
    }
  }

  // 更新画布
  update(){

    this.clear();
    this.resize();
    this.drawBorder();
    this.drawGrid();

    this.renderItems();

    this.updateHelper();
  }

  // 清空画布
  clear(){
    const canvas = this.canvas;

    if (canvas.getContext){
      var ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    } 

    canvas.style.backgroundColor = this.bgColor;
  }
}

export default Canvas2DBase;